#include <stdio.h>
#include <stdbool.h>

#define	BOARD_COLUMNS	7
#define BOARD_ROWS		6
#define CONNECT_NUM		4

//#define DRAW_NUMBERS	// true

// console colour escape codes
char red[] = { 0x1b, '[', '3', '1', ';', '4', '1', 'm', 0 };	// following text red
char yellow[] = { 0x1b, '[', '3', '3', ';', '4', '3', 'm', 0 };	// following text yellow
char normal[] = { 0x1b, '[', '0', ';', '3', '9', 'm', 0 };		// black bg, white text

// column, row coorinates struct
typedef struct s_position
{
	int col;
	int row;
} s_position;

	unsigned char array[BOARD_COLUMNS][BOARD_ROWS];	// columns, rows
		
	int playerOneColour;
	int playerTwoColour;
		
	int total_turns;	// keep track of the number of turns this game has had
		
	int player_turn;	// which players turn is it (1 or 2)
		
	s_position last_move;	// 'coordinates' of last move
	
		
	void setPlayerColour(int player, int colour);
	// sets 
	
	bool dropPieceInColumn(int player, int col);
	// drops a piece in column col. returns false if column is full
		
	int checkConnect4();
	// checks if a connect 4 has occured
	// returns the number of the player that has won
	// or (-1, no win) or (-2, cats game)
		
	int getPlayerTurn();
	// returns which players turn it is
		
	void draw();
	// draws the game board
		
	void clear();
	// clears the game board (removes all pieces)

/**
*
* Functions:
*
**/

// sets the player piece colour
void setPlayerColour(int player, int colour)
{
	if (player == 1)
		playerOneColour = colour;
	else
		playerTwoColour = colour;
}

// drops a piece in column col. returns false if column is full
bool dropPieceInColumn(int player, int col)
{
	// look for the next open spot in the column
	int i;
	for (i=0; i<BOARD_ROWS; i++)
	{
		if (array[col][i] == 0)
		{
			array[col][i] = (unsigned char) (player == 1) ? playerOneColour : playerTwoColour;	// drop piece
			total_turns++;	// increment total turns
			player_turn = (player_turn == 1) ? 2 : 1;	// toggle player turn
			last_move.col = col;
			last_move.row = i;
			return true;
		}
	}
	return false;
}

// checks if a connect 4 has occured
// returns the number of the player that has won
// or (-1, no win) or (-2, cats game)
int checkConnect4()
{
	if (last_move.col == -1 || last_move.row == -1)
		return -1;
	
	s_position tmp;
	unsigned char curr_colour;
	int in_a_row;
	
	/// look for 4 in a row four directions: up/down, left/right, diagonal1, diag2
	
	// diagonal up left
	for(tmp.col=last_move.col, tmp.row=last_move.row; 	// start from bottom right
		tmp.col < BOARD_COLUMNS && tmp.row > 0;
		tmp.col++, tmp.row--);
		
	for(curr_colour=array[tmp.col][tmp.row], in_a_row=0;
		tmp.col > 0 && tmp.row < BOARD_ROWS;			// check for 4 in a row, up to left
		tmp.col--, tmp.row++)
	{
		if (array[tmp.col][tmp.row] == curr_colour && curr_colour != 0)
		{
			if (++in_a_row == CONNECT_NUM)	return (curr_colour == playerOneColour) ? 1 : 2;
		}
		else 
		{
			curr_colour = array[tmp.col][tmp.row];
			in_a_row = 1;
		}
	}
	
	// diagonal up right
	for(tmp.col=last_move.col, tmp.row=last_move.row; 	// start from bottom left
		tmp.col > 0 && tmp.row > 0;
		tmp.col--, tmp.row--);
		
	for(curr_colour=array[tmp.col][tmp.row], in_a_row=0;
		tmp.col < BOARD_COLUMNS && tmp.row < BOARD_ROWS;			// check for 4 in a row, up to right
		tmp.col++, tmp.row++)
	{
		if (array[tmp.col][tmp.row] == curr_colour && curr_colour != 0)
		{
			if (++in_a_row == CONNECT_NUM)	return (curr_colour == playerOneColour) ? 1 : 2;
		}
		else 
		{
			curr_colour = array[tmp.col][tmp.row];
			in_a_row = 1;
		}
	}
	
	// up/down
	tmp.col = last_move.col;
	tmp.row = 0; 	// start from bottom

	for(curr_colour=array[tmp.col][tmp.row], in_a_row=0;
		tmp.row < BOARD_ROWS;			// check for 4 in a row, up
		tmp.row++)
	{
		if (array[tmp.col][tmp.row] == curr_colour && curr_colour != 0)
		{
			if (++in_a_row == CONNECT_NUM)	return (curr_colour == playerOneColour) ? 1 : 2;
		}
		else 
		{
			curr_colour = array[tmp.col][tmp.row];
			in_a_row = 1;
		}
	}
	
	// left/right
	tmp.col = 0;
	tmp.row = last_move.row; 	// start from left

	for(curr_colour=array[tmp.col][tmp.row], in_a_row=0;
		tmp.col < BOARD_COLUMNS;			// check for 4 in a row, up
		tmp.col++)
	{
		if (array[tmp.col][tmp.row] == curr_colour && curr_colour != 0)
		{
			if (++in_a_row == CONNECT_NUM)	return (curr_colour == playerOneColour) ? 1 : 2;
		}
		else 
		{
			curr_colour = array[tmp.col][tmp.row];
			in_a_row = 1;
		}
	}
	
	// check for cats game
	for (tmp.row = BOARD_ROWS-1, tmp.col = 0;
		tmp.col < BOARD_COLUMNS;
		tmp.col++)
	{
		if (array[tmp.col][tmp.row] == 0)
			break;
		else if(tmp.col == BOARD_COLUMNS-1)
			return -2;	// cats!
	}
	
	// no win yet
	return -1;
}


// draws the game board
void draw_board()
{
	printf("\n");
	int i, j;
	for (j=BOARD_ROWS-1; j >= 0; j--)
	{
		printf("  -----------------------------\n");
		#ifdef DRAW_NUMBERS
			printf("%d", j+1);
		#else
			printf(" ");
		#endif
		for (i=0; i < BOARD_COLUMNS; i++)
		{
			printf(" | ");
			printf("%d", array[i][j]);
		}
		printf(" |\n");
	}
	printf("  -----------------------------\n");
	printf("    1   2   3   4   5   6   7\n");
}


// clears the game board (removes all pieces)
void clear()
{
	// clear game board
	int i, j;
	for (i=0; i<BOARD_COLUMNS; i++)
	{
		for (j=0; j<BOARD_ROWS; j++)
		{
			array[i][j] = 0;
		}
	}
}

void _clearScreen()
{
	printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
}

int main()
{
	int input;

	// clear game board
	clear();
	// set default player 'colours'
	setPlayerColour(1, 1);
	setPlayerColour(2, 2);
	// init
	player_turn = 1;	// randomize?
	total_turns = 0;
	last_move.col = -1;
	last_move.row = -1;
	
	while(checkConnect4() == -1)
	{
		_clearScreen();
		printf("       ---- CONNECT 4 ----        (type -1 to exit)");
		draw_board();
		printf("\nTurn: Player %d", player_turn);

		printf("\nPlace piece in which column (1-7)? ");
		scanf("%d",&input);
		
		if ( input==-1 )
			return 0;
		if (input < 8 && input > 0)
			dropPieceInColumn(player_turn, input-1);
	}
	
	//_clearScreen();
	draw_board();
	if (checkConnect4() == -2)
	{
		printf("\nCats Game!");
	}
	else
	{
		printf("\nPlayer %d wins!\n", checkConnect4());
	}
	
	printf("\n");

	return 0;
}
